package it.antonio.ilpizze.assertion;


public abstract class Assertion<T> {

        protected T instance;

        protected String description;
        protected String errorMessage;

        protected Assertion(T instance) {
                super();
                this.instance = instance;
                if(instance != null){
                        description = instance.toString();
                }
        }
        public void isNull(){
                if (instance == null)
                        return;
                fail("should be null");
        }

        public abstract Assertion<T> satisfies(Condition condition);

        public abstract Assertion<T> doesNotSatisfy(Condition condition);

        public abstract Assertion<T> as(String description);

        public abstract Assertion<T> isEqualTo(T expected);

        public abstract Assertion<T> isNotEqualTo(T other);

        public abstract Assertion<T> isNotNull();

        public abstract Assertion<T> isSameAs(T expected);

        public abstract Assertion<T> isNotSameAs(T other);

        protected void assertNotNull() {
                if (instance != null) return;
                fail("expecting a non-null object, but it was null");
        }

        protected void assertNotEqual(T anotherInstance) {
                assertNotNull();
                if (!instance.equals(anotherInstance))
                        return;
                fail("not expecting equals objects");
        }

        protected void assertEqual(T anotherInstance) {
                assertNotNull();
                if (instance.equals(anotherInstance))
                        return;
                fail("expecting equals objects");
        }

        protected void assertSatisfy(Condition condition) {
                assertNotNull();
                if (condition != null && condition.match())     return;
                fail("condition not satisfied");
        }
        protected void assertNotSatisfy(Condition condition) {
                assertNotNull();
                if (condition != null && !condition.match())    return;
                fail("condition satisfied");
        }

        protected void assertIsSameAs(T expected) {
                if(instance == expected) return;
                fail("they are not the same");
        }
        
        protected void assertIsNotSameAs(T other) {
                if(instance != other) return;
                fail("they are the same");
        }

        protected void description(String description) {
                this.description = description;
        }

        protected void errorMessage(String errorMessage) {
                this.errorMessage = errorMessage;
        }

        protected void fail(String message) {
                StringBuffer msgBuffer = new StringBuffer();
                msgBuffer.append("<" + description + ">: ");
                if (errorMessage != null) {
                        msgBuffer.append(errorMessage);
                } else {
                        msgBuffer.append(message);
                }
                throw new AssertionError(msgBuffer.toString());
        }

}
